---
title: Permissions
---

## User and Roles

Spree by default comes with `admin` and `user` roles. You can create more roles in the Admin Panel UI or rails console / seed, eg.:

```ruby
Spree::Role.find_or_create_by(name: 'customer_service')
```

Same with assigning a role, you can do it in the Admin Panel or from the console:

```ruby
Spree.user_class.find_by(email: 'john@example.com').spree_roles << Spree::Role.find_or_create_by(name: 'customer_service')
```

## Ability class

For authorization Spree uses [CanCanCan](https://github.com/CanCanCommunity/cancancan) library. The main ability class by default is [Spree::Ability](https://github.com/spree/spree/blob/main/core/app/models/spree/ability.rb).

## Adding custom permissions

Let's assume you would like to add a new Role `customer_service` with some limited access to Admin Panel only Orders section.

Create a new file called `app/models/customer_service_ability.rb`

```ruby
class CustomerServiceAbility
  include CanCan::Ability

  def initialize(user)
    if user.respond_to?(:has_spree_role?) && user.has_spree_role?('customer_service')
      can :manage, Spree::Order
    end
  end
end
```

Please familiarize yourself with [CanCanCan](https://github.com/CanCanCommunity/cancancan) syntax to understand `can/cannot` methods more.

Now we need to inform Spree to use this ability, create another file `app/models/spree/ability_decorator.rb` with contents:

```ruby
module Spree
  module AbilityDecorator
    def abilities_to_register
      [CustomerServiceAbility]
    end
  end

  Ability.prepend(AbilityDecorator)
end
```

## Replacing all permissions

As we've mentioned earlier, Spree uses the main Ability class. You can change that to use your own custom Ability class via [Dependencies](dependencies) in Spree initializer `config/initializers/spree.rb`, eg.

```ruby
Spree::Dependencies.ability_class = 'CustomAbility'
```

Now, let's define that new class in `app/models/custom_ability.rb`

```ruby
class CustomAbility < Spree::Ability
  def initialize(user)
    alias_cancan_delete_action

    user ||= Spree.user_class.new

    if user.respond_to?(:has_spree_role?) && user.has_spree_role?('admin')
      apply_admin_permissions(user)
      # add some more permissions here for the admin role
    else 
      if user.respond_to?(:has_spree_role?) && user.has_spree_role?(:customer_service)
        apply_customer_service_permissions(user)
      end

      apply_user_permissions(user)
    end

    protect_admin_role
  end

  protected

  def apply_customer_service_permissions(user)
    can :manage, Spree::Order
  end
end
```

After restarting the rails server you observe new permissions being recognized in the application.

Further permission changes should be automatically picked up in development and should not require application restarts.
